package com.whfc.fse.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.common.enums.BindFlag;
import com.whfc.common.enums.NetState;
import com.whfc.common.exception.BizException;
import com.whfc.common.result.ListData;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.spring.AppContextUtil;
import com.whfc.common.util.PageUtil;
import com.whfc.fse.dao.FseCraneDataMapper;
import com.whfc.fse.dao.FseCraneMapper;
import com.whfc.fse.dao.FseCraneToolMapper;
import com.whfc.fse.dto.*;
import com.whfc.fse.entity.FseCrane;
import com.whfc.fse.entity.FseCraneData;
import com.whfc.fse.entity.FseCraneTool;
import com.whfc.fse.param.*;
import com.whfc.fse.service.FseCraneService;
import com.whfc.fuum.service.SysDeptService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 塔机服务
 *
 * @author GuoDong_Sun
 * @date 2020/4/8
 */
@DubboService(interfaceClass = FseCraneService.class, version = "1.0.0", timeout = 5000)
public class FseCraneServiceImpl implements FseCraneService {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private FseCraneMapper fseCraneMapper;

    @Autowired
    private FseCraneDataMapper fseCraneDataMapper;

    @Autowired
    private FseCraneToolMapper fseCraneToolMapper;

    @DubboReference(interfaceClass = SysDeptService.class, version = "1.0.0")
    private SysDeptService sysDeptService;

    @Override
    public PageData<FseCraneDTO> list(Integer pageNum, Integer pageSize, Integer deptId, String keyword,
                                      Integer bindFlag, Integer netState) {
        logger.info("塔机列表服务,pageNum:{},pageSize:{},deptId:{},keyword:{},bindFlag:{},netState:{}",
                pageNum, pageSize, deptId, keyword, bindFlag, netState);
        PageHelper.startPage(pageNum, pageSize);
        List<FseCraneDTO> list = fseCraneMapper.selectFseCraneByDeptId(deptId, keyword, bindFlag, netState);
        PageHelper.clearPage();
        // 处理操作手以及监控信息
        for (FseCraneDTO fseCraneDTO : list) {
            List<FseOperatorDTO> operatorList = parseOperators(fseCraneDTO.getOperators());
            fseCraneDTO.setOperatorList(operatorList);
            fseCraneDTO.setOperators(null);
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public ListData<OpenApiFseCraneDTO> list(Integer deptId) throws BizException {
        List<OpenApiFseCraneDTO> list = fseCraneMapper.selectOpenApiFseCraneByDeptId(deptId);
        for (OpenApiFseCraneDTO fseCraneDTO : list) {
            // 处理操作手
            List<FseOperatorDTO> operatorList = parseOperators(fseCraneDTO.getOperators());
            fseCraneDTO.setOperatorList(operatorList);
            fseCraneDTO.setOperators(null);

            //处理监控设备
            List<FseCraneFvsDeviceDTO> fvsDeviceList = parseFvsDevices(fseCraneDTO.getFvsDevices());
            List<OpenApiFseDeviceDTO> openApiFseDeviceList = new ArrayList<>();
            for (FseCraneFvsDeviceDTO fseCraneFvsDeviceDTO : fvsDeviceList) {
                OpenApiFseDeviceDTO fseDeviceDTO = new OpenApiFseDeviceDTO();
                fseDeviceDTO.setDeviceId(fseCraneFvsDeviceDTO.getFvsDeviceId());
                fseDeviceDTO.setName(fseCraneFvsDeviceDTO.getFvsDeviceName());
                openApiFseDeviceList.add(fseDeviceDTO);
            }
            fseCraneDTO.setVideoList(openApiFseDeviceList);
            fseCraneDTO.setFvsDevices(null);
        }
        return new ListData<>(list);
    }

    @Override
    public void add(FseCraneAddParam request) {
        logger.info("添加塔机服务,param:{}", request.toString());
        String code = request.getCode();
        Integer deptId = request.getDeptId();
        FseCrane fseCrane = fseCraneMapper.selectByDeptIdAndCode(deptId, code);
        if (fseCrane != null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "此设备编号已存在，不能重复添加");
        }
        FseCrane record = new FseCrane();
        BeanUtils.copyProperties(request, record);
        //处理操作手
        List<FseOperatorDTO> operatorList = request.getOperatorList();
        if (operatorList != null) {
            String operators = JSON.toJSONString(operatorList);
            record.setOperators(operators);
        }
        fseCraneMapper.insertSelective(record);
        // 初始化最新数据
        initCraneData(record.getId());
    }


    @Override
    public void edit(FseCraneEditParam request) {
        logger.info("编辑塔机服务,param:{}", request.toString());
        Integer craneId = request.getCraneId();
        FseCrane fseCrane = fseCraneMapper.selectByPrimaryKey(craneId);
        if (fseCrane == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该塔机不存在");
        }
        String code = request.getCode();
        Integer deptId = fseCrane.getDeptId();
        FseCrane fseCrane1 = fseCraneMapper.selectByDeptIdAndCode(deptId, code);
        if (fseCrane1 != null && !fseCrane1.getId().equals(craneId)) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "此设备编号已存在，不能重复添加");
        }

        FseCrane record = new FseCrane();
        BeanUtils.copyProperties(request, record);
        record.setId(craneId);
        //保存操作手
        List<FseOperatorDTO> list = request.getOperatorList();
        if (list == null) {
            list = new ArrayList<>();
        }
        record.setOperators(JSON.toJSONString(list));
        fseCraneMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public void del(Integer id) throws BizException {
        logger.info("删除塔机服务,id:{}", id);
        FseCrane fseCrane = fseCraneMapper.selectByPrimaryKey(id);
        if (fseCrane == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该塔机不存在");
        }
        if (BindFlag.BIND.getValue().equals(fseCrane.getBindFlag())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该塔机已绑定硬件,不能删除");
        }
        fseCraneMapper.deleteLogicById(id);
    }

    @Override
    public void bind(FseCraneBindParam request) {
        logger.info("塔机绑定硬件服务,param:{}", request.toString());
        Integer craneId = request.getCraneId();
        FseCrane fseCrane = fseCraneMapper.selectByPrimaryKey(craneId);
        if (fseCrane == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该塔机不存在");
        }
        if (BindFlag.BIND.getValue().equals(fseCrane.getBindFlag())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该塔机已绑定硬件,不能重复绑定");
        }
        Integer deptId = fseCrane.getDeptId();
        String sn = request.getSn();
        String platform = request.getPlatform();
        FseCrane crane = fseCraneMapper.selectByPlatformAndSn(platform, sn);
        if (crane != null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该硬件已被绑定");
        }

        //修改塔机的绑定状态
        fseCraneMapper.updateBindFlag(craneId, platform, BindFlag.BIND.getValue(), sn, NetState.OFFLINE.getValue());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void unbind(Integer craneId) {
        logger.info("塔机解绑硬件服务,craneId:{}", craneId);
        FseCrane fseCrane = fseCraneMapper.selectByPrimaryKey(craneId);
        if (fseCrane == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该塔机不存在");
        }
        if (BindFlag.UNBIND.getValue().equals(fseCrane.getBindFlag())) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该塔机未绑定硬件");
        }
        //修改塔机的绑定状态
        fseCraneMapper.updateBindFlag(craneId, null, BindFlag.UNBIND.getValue(), null, NetState.OFFLINE.getValue());
    }

    @Override
    public ListData<FseCraneDTO> list(Integer deptId, Integer bindFlag) {
        logger.info("塔机列表服务,deptId:{},bindFlag:{}", deptId, bindFlag);
        List<Integer> deptIds = sysDeptService.getDescendantDeptIdList(deptId);
        List<FseCraneDTO> list = fseCraneMapper.selectFseCraneList(deptIds, bindFlag);
        return new ListData<>(list);
    }
    @Override
    public List<FseCraneDTO> listV2(Integer deptId) {
        List<FseCraneDTO> list = fseCraneMapper.selectFseCraneByDeptId(deptId, null, null, null);

        // 处理操作手以及监控信息
        for (FseCraneDTO fseCraneDTO : list) {
            List<FseOperatorDTO> operatorList = parseOperators(fseCraneDTO.getOperators());
            fseCraneDTO.setOperatorList(operatorList);
            fseCraneDTO.setOperators(null);
        }

        return list;
    }

    @Override
    public List<FseCraneDTO> list(Integer deptId, String platform) throws BizException {
        return fseCraneMapper.selectFseCraneByDeptIdAndPlatform(deptId,platform);
    }

    @Override
    public FseCraneDTO detail(Integer craneId) {
        logger.info("塔机详情服务,craneId:{}", craneId);
        FseCrane fseCrane = fseCraneMapper.selectByPrimaryKey(craneId);
        FseCraneDTO fseCraneDTO = new FseCraneDTO();
        BeanUtils.copyProperties(fseCrane, fseCraneDTO);
        fseCraneDTO.setCraneId(fseCrane.getId());
        //查询操作手
        List<FseOperatorDTO> operatorList = parseOperators(fseCrane.getOperators());
        fseCraneDTO.setOperatorList(operatorList);
        fseCraneDTO.setOperators(null);
        //查询监控列表
        List<FseCraneFvsDeviceDTO> fvsDeviceList = parseFvsDevices(fseCrane.getFvsDevices());
        fseCraneDTO.setFvsList(fvsDeviceList);
        fseCraneDTO.setFvsDevices(null);
        return fseCraneDTO;
    }

    @Override
    public List<FseCraneFvsDeviceDTO> getFvsDeviceList(Integer craneId) throws BizException {
        List<FseCraneFvsDeviceDTO> list = new ArrayList<>();
        FseCrane fseCrane = fseCraneMapper.selectByPrimaryKey(craneId);
        if (fseCrane != null) {
            String fvsDevices = fseCrane.getFvsDevices();
            list = parseFvsDevices(fvsDevices);
        }
        return list;
    }

    @Override
    public void bindFvs(FseCraneFvsParam fseCraneFvsParam) throws BizException {
        //绑定新的监控设备
        List<FseFvsDeviceParam> list = fseCraneFvsParam.getFvsList();
        if (list == null || list.isEmpty()) {
            return;
        }
        List<FseCraneFvsDeviceDTO> fseCraneFvsDevices = new ArrayList<>();
        for (FseFvsDeviceParam fseFvsDeviceParam : list) {
            FseCraneFvsDeviceDTO fseCraneFvsDevice = new FseCraneFvsDeviceDTO();
            fseCraneFvsDevice.setCranePart(fseFvsDeviceParam.getCranePart());
            fseCraneFvsDevice.setFvsDeviceId(fseFvsDeviceParam.getFvsDeviceId());
            fseCraneFvsDevice.setFvsDeviceName(fseFvsDeviceParam.getFvsDeviceName());
            fseCraneFvsDevices.add(fseCraneFvsDevice);
        }
        String fvsDevices = JSON.toJSONString(fseCraneFvsDevices);
        fseCraneMapper.updateFvsDevices(fseCraneFvsParam.getCraneId(), fvsDevices);
    }


    @Override
    public PageData<FseCraneToolDTO> getCraneToolList(Integer deptId, Integer pageNum, Integer pageSize) throws BizException {
        PageHelper.startPage(pageNum, pageSize);
        List<FseCraneToolDTO> list = fseCraneToolMapper.selectCraneToolList(deptId);
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public void addCraneTool(FseCraneToolAdd param) throws BizException {
        FseCraneTool tool = new FseCraneTool();
        BeanUtils.copyProperties(param, tool);
        fseCraneToolMapper.insertSelective(tool);
    }

    @Override
    public void editCraneTool(FseCraneToolEdit param) throws BizException {
        FseCraneTool tool = new FseCraneTool();
        BeanUtils.copyProperties(param, tool);
        tool.setId(param.getToolId());
        fseCraneToolMapper.updateByPrimaryKeySelective(tool);
    }

    @Override
    public void delCraneTool(Integer toolId) throws BizException {
        fseCraneToolMapper.logicDeleteById(toolId);
    }


    /**
     * 处理操作手
     *
     * @param operators 操作手 JSON
     * @return 操作手集合
     */
    private List<FseOperatorDTO> parseOperators(String operators) {
        List<FseOperatorDTO> operatorList = JSON.parseArray(operators, FseOperatorDTO.class);
        if (operatorList == null) {
            operatorList = new ArrayList<>();
        }
        return operatorList;
    }

    /**
     * 处理监控设备
     *
     * @param fvsDevices 监控设备 JSON
     * @return 监控设备集合
     */
    private List<FseCraneFvsDeviceDTO> parseFvsDevices(String fvsDevices) {
        List<FseCraneFvsDeviceDTO> fvsDeviceList = JSON.parseArray(fvsDevices, FseCraneFvsDeviceDTO.class);
        if (fvsDeviceList == null) {
            fvsDeviceList = new ArrayList<>();
        }
        return fvsDeviceList;
    }


    /**
     * 初始化塔机数据
     *
     * @param craneId 塔机ID
     */
    private void initCraneData(Integer craneId) {
        FseCraneData fseCraneData = new FseCraneData();
        fseCraneData.setCraneId(craneId);
        fseCraneData.setForeArmLength(0D);
        fseCraneData.setRearArmLength(0D);
        fseCraneData.setTowerArmHeight(0D);
        fseCraneData.setHeight(0D);
        fseCraneData.setWeight(0D);
        fseCraneData.setRange(0D);
        fseCraneData.setMomentRatio(0D);
        fseCraneData.setWindSpeed(0D);
        fseCraneData.setDipAngle(0D);
        fseCraneData.setTurnAngle(0D);
        fseCraneDataMapper.insertSelective(fseCraneData);
    }


}
